package com.example.util;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @Classname ClazzScanUtils
 * @Description TODO
 * @Date 2023/4/24 15:03
 * @Created by XiongXiong
 * @Author: X.I.O
 */
public class ClassScanUtils {

    private static ConcurrentHashMap<String,Object> cache = new ConcurrentHashMap<>();

    private static List<String> classPaths=new ArrayList<>();

    private static List<Class<?>> classList=new ArrayList<>();


    /**
     * 应用加载和重启专用
     * @param path
     * @param jarName
     */
    public static void onload(String path,String jarName){
        try {
            JarScanClassUtils.clear();
            Set<Class<?>> cls=JarScanClassUtils.loadAllJarFromAbsolute(path);
            List< Class< ? >> classes = new ArrayList<>();
            for (Class< ? > c : cls) {
                classes.add(c);
            }
            System.out.println(path+"【合法应用, 开始加载】");
            JarScanClassUtils.addAllSet(cls);
            addClazz(classes);

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private static void addClazz(List<Class< ? >> classList){
        try {
            //ObjectMaps.createClazzList(classList);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void scanClass(Class<?> clazz) throws ClassNotFoundException {
        //包名
        String basePack = clazz.getPackage().getName();
        if(clazz.getResource("/")==null){
            return;
        }
        //先把包名转换为路径,首先得到项目的classpath
        String classpath = clazz.getResource("/").getPath();
        //然后把我们的包名basPach转换为路径名
        basePack = basePack.replace(".", File.separator);
        //然后把classpath和basePack合并
        String searchPath = classpath + basePack;
        doPath(new File(searchPath));
        //这个时候我们已经得到了指定包下所有的类的绝对路径了。我们现在利用这些绝对路径和java的反射机制得到他们的类对象
        for (String s : classPaths) {
            s = s.replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"").replace("\\",".").replace(".class","");
            Class cls = Class.forName(s);
            classList.add(cls);
        }
    }
    /**
     * 该方法会得到所有的类，将类的绝对路径写入到classPaths中
     * @param file
     */
    private static void doPath(File file) {
        if (file.isDirectory()) {//文件夹
            //文件夹我们就递归
            File[] files = file.listFiles();
            for (File f1 : files) {
                doPath(f1);
            }
        } else {//标准文件
            //标准文件我们就判断是否是class文件
            if (file.getName().endsWith(".class")) {
                //如果是class文件我们就放入我们的集合中。
                classPaths.add(file.getPath());
            }
        }
    }

    public static List<Class<?>> getClassPaths(){
        return classList;
    }

    public static void searchClass(Class< ? > clazz) throws IOException, ClassNotFoundException {
        String basePack = clazz.getPackage().getName();
        System.out.println(basePack);
        //通过当前线程得到类加载器从而得到URL的枚举
        Enumeration<URL> urlEnumeration = Thread.currentThread().getContextClassLoader().getResources(basePack.replace(".", "/"));
        try {
            while (urlEnumeration.hasMoreElements()) {
                URL url = urlEnumeration.nextElement();//得到的结果大概是：jar:file:/C:/Users/ibm/.m2/repository/junit/junit/4.12/junit-4.12.jar!/org/junit
                String protocol = url.getProtocol();//大概是jar
                if ("jar".equalsIgnoreCase(protocol)) {
                    //转换为JarURLConnection
                    JarURLConnection connection = (JarURLConnection) url.openConnection();
                    if (connection != null) {
                        JarFile jarFile = connection.getJarFile();
                        if (jarFile != null) {
                            //得到该jar文件下面的类实体
                            Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
                            while (jarEntryEnumeration.hasMoreElements()) {
                                JarEntry entry = jarEntryEnumeration.nextElement();
                                String jarEntryName = entry.getName();
                                //这里我们需要过滤不是class文件和不在basePack包名下的类
                                if (jarEntryName.contains(".class") && jarEntryName.replaceAll("/",".").startsWith(basePack)) {
                                    String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replace("/", ".");
                                    classPaths.add(className);
                                    Class< ? > clsClass=Class.forName(className);
                                    classList.add(clsClass);
                                }
                            }
                        }
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}
